import re
from django import forms
from django.contrib import auth
from django.core.cache import cache
from django.contrib.auth.models import User

class LoginForm(forms.Form):
    login_name = forms.CharField(label='用户名或邮箱', widget=forms.TextInput(
                                                        attrs={'class':'form-control', 'placeholder':'用户名或激活邮箱'}))
    password = forms.CharField(label='密码', widget=forms.PasswordInput(
                                                        attrs={'class':'form-control', 'placeholder':'密码'}))
    
    def clean(self):
        login_name = self.cleaned_data['login_name']
        password = self.cleaned_data['password']
        user = auth.authenticate(username=login_name, password=password)
        if user is not None:
            # 通过用户名验证成功
            self.cleaned_data['user'] = user
            return self.cleaned_data
        else:
            # 尝试邮箱登录
            if User.objects.filter(email=login_name).exists():
                username = User.objects.get(email=login_name).username
                user = auth.authenticate(username=username, password=password)
                if user is not None:
                    # 通过邮箱验证成功
                    self.cleaned_data['user'] = user
                    return self.cleaned_data
        raise forms.ValidationError('用户不存在或密码有误')

class RegForm(forms.Form):
    username = forms.CharField(min_length=3, max_length=30, label='用户名(3-30个字符)', widget=forms.TextInput(
                                                        attrs={'class':'form-control', 'placeholder':'用户名'}))
    email = forms.EmailField(label='邮箱', widget=forms.EmailInput(attrs={'class':'form-control', 'placeholder':'邮箱'}))
    password = forms.CharField(min_length=6,max_length=20, label='密码(6-20位)', widget=forms.PasswordInput(
                                                        attrs={'class':'form-control', 'placeholder':'密码'}))
    password_again = forms.CharField(min_length=6,max_length=20, label='密码确认', widget=forms.PasswordInput(
                                                        attrs={'class':'form-control', 'placeholder':'密码确认'}))
                                                    
    def clean_username(self):
        if User.objects.filter(username=self.cleaned_data['username']).exists():
            raise forms.ValidationError('用户名已存在', code='AlreadyExist')
        return self.cleaned_data['username']
    
    def clean_email(self):
        if User.objects.filter(email=self.cleaned_data['email']).exists():
            raise forms.ValidationError('邮箱已被注册', code='AlreadyRegistered')
        return self.cleaned_data['email']
    
    def clean_password_again(self):
        password = self.cleaned_data['password']
        password_again = self.cleaned_data['password_again']
        if password != password_again:
            raise forms.ValidationError('两次输入密码不一致',code='DoNotMatch')
        return self.cleaned_data['password_again']

class NickNameForm(forms.Form):
    '''
    修改昵称使用的表单
    '''
    new_nickname = forms.CharField(max_length=20, label='新的昵称', widget=forms.TextInput(attrs = 
                                        {'class':'form-control', 'placeholder':'新的昵称'}))
    
    def __init__(self, *args, **kwargs):
        if 'user' in kwargs:
            self.user = kwargs.pop('user')
        super(NickNameForm, self).__init__(*args, **kwargs)

    def clean_new_nickname(self):
        new_nickname = self.cleaned_data['new_nickname'].strip()
        if new_nickname == '':
            raise forms.ValidationError('昵称不能为空')
        return new_nickname
    
    def clean(self):
        if not self.user.is_authenticated:
            raise ValidationError('用户未登录')
        else:
            self.cleaned_data['user'] = self.user
            return self.cleaned_data
            
class EmailForm(forms.Form):
    '''
    绑定邮箱时的表单
    '''
    email = forms.EmailField(label='绑定的邮箱', widget=forms.EmailInput(attrs=
                                        {'class':'form-control', 'placeholder':'请输入绑定的邮箱', 'id':'connected_email'}))
    
    def __init__(self, *args, **kwargs):
        if 'user' in kwargs:
            self.user = kwargs.pop('user')
        super(EmailForm, self).__init__(*args, **kwargs)

    def clean_email(self):
        # 判断邮箱格式
        email = self.cleaned_data['email']
        m = re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', email)
        if not m:
            # 正则表达式失效
            raise forms.ValidationError('邮箱格式异常')
        # 判断邮箱是否被注册
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError('该邮箱已被注册')
        return email
    
    def clean(self):
        # 判断用户是否登录
        if self.user.is_authenticated:
            self.cleaned_data['user'] = self.user
        else:
            raise forms.ValidationError('用户未登录')

        return self.cleaned_data

class ResetPasswordForm(forms.Form):
    '''
    处于登录状态，重置密码的表单
    '''
    old_password = forms.CharField(label='旧的密码', widget=forms.PasswordInput(attrs=
                                                    {'class':"form-control", 'placeholder':'输入旧的密码'}))
    new_password = forms.CharField(label='新的密码',min_length=6, max_length=20, widget=forms.PasswordInput(attrs=
                                                    {'class':"form-control", 'placeholder':'输入新的密码'}))
    new_password_again = forms.CharField(label='重复输入新的密码',min_length=6, max_length=20, widget=forms.PasswordInput(attrs=
                                                    {'class':"form-control", 'placeholder':'再次输入新的密码'}))
    def __init__(self, *args, **kwargs):
        if 'user' in kwargs:
            self.user = kwargs.pop('user')
        super(ResetPasswordForm, self).__init__(*args, **kwargs)

    def clean_old_password(self):
        old_password = self.cleaned_data['old_password']
        user = auth.authenticate(username=self.user.username, password=old_password)
        if user is None:
            raise forms.ValidationError('密码错误')
        return old_password
    
    def clean(self):
        # 首先判断用户是否登录
        if not self.user.is_authenticated:
            raise forms.ValidationError('用户未登录')
        self.cleaned_data['user'] = self.user
        # 判断新密码是否合法
        new_password = self.cleaned_data['new_password']
        new_password_again = self.cleaned_data['new_password_again']
        if new_password != new_password_again:
            raise forms.ValidationError('两次密码不一致')
        elif len(new_password) < 6 or len(new_password) > 20:
            raise forms.ValidationError('新密码长度有误')
        return self.cleaned_data

class RetrievePasswordForm(forms.Form):
    '''
    用于忘记密码后找回
    '''
    email = forms.EmailField(label='注册邮箱', widget=forms.EmailInput(attrs=
                                {'class':'form-control', 'placeholder':'输入注册时邮箱', 'id':'retrieve_email'}))
    captcha = forms.CharField(label='验证码', widget=forms.TextInput(attrs=
                                {'class':'form-control', 'placeholder':'输入验证码'}))
    new_password = forms.CharField(label='新的密码',min_length=6, max_length=20, widget=forms.PasswordInput(attrs=
                                                    {'class':"form-control", 'placeholder':'输入新的密码'}))
    new_password_again = forms.CharField(label='重复输入新的密码',min_length=6, max_length=20, widget=forms.PasswordInput(attrs=
                                                    {'class':"form-control", 'placeholder':'再次输入新的密码'}))
    
    def clean_email(self):
        email = self.cleaned_data['email']
        m = re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', email)
        if not m:
            # 正则表达式匹配失败
            raise forms.ValidationError('邮箱格式异常')
        # 判断邮箱是否被注册
        if not User.objects.filter(email=email).exists():
            raise forms.ValidationError('该邮箱未被注册')
        return email
    
    def clean(self):
        '''
        这个方法会在之前的clean_xxx后调用
        '''
        # 获取对应用户
        user = User.objects.get(email=self.cleaned_data['email'])
        self.cleaned_data['user'] = user
        # 判断验证码是否正确
        cache_key = 'retrieve_captcha_{}'.format(user.pk)
        captcha_cache = cache.get(cache_key)
        if captcha_cache is None:
            raise forms.ValidationError('验证码无效')
        if captcha_cache.get('captcha', '') != self.cleaned_data['captcha']:
            raise forms.ValidationError('验证码错误')
        self.cleaned_data['cache_key'] = cache_key
        # 判断两次密码
        new_password = self.cleaned_data['new_password']
        new_password_again = self.cleaned_data['new_password_again']
        if new_password != new_password_again:
            raise forms.ValidationError('两次密码不一致')
        elif len(new_password) < 6 or len(new_password) > 20:
            raise forms.ValidationError('新密码长度有误')
        return self.cleaned_data
        